package com.laoli.springioc.handler.scan;


import com.laoli.springioc.handler.annotation.MyResource;
import com.laoli.springioc.handler.annotation.MyService;
import com.laoli.springioc.javax.common.utils.ClassUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class Scanner {

    private static Config config = new Config("application");
    private static String BEAN_PACKAGE_PATH = config.get("beanPath");
    public static ConcurrentHashMap<String, Object> initBean  = new ConcurrentHashMap<String, Object>();

    /**
     * 根据beanid获取对应的bean
     * @param beanId
     * @return
     * @throws Exception
     */

    public Object getBean(String beanId) throws Exception {
        List<Class<?>> classes = getClasses(BEAN_PACKAGE_PATH);
        if (classes == null || classes.isEmpty()) {
            throw new Exception("no found anything bean is useding initial..");
        }
        initBean = initBean(classes);
        if (initBean == null || initBean.isEmpty()) {
            throw new Exception("initial bean is empty or null");
        }
        Object object = initBean.get(beanId);
        //初始化属性的依赖
        initAttribute(object);
        return object;
    }

    public ConcurrentHashMap<String, Object> initBean(List<Class<?>> classes) throws IllegalAccessException, InstantiationException {
        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
        String beanId="";
        for(Class clazz :classes){
            boolean anInterface = clazz.isInterface();
            if (!anInterface){
                Object object = clazz.newInstance();
                MyService annotation =(MyService)clazz.getDeclaredAnnotation(MyService.class);
                if (annotation!=null){
                    //如果定义了name属性 以实现的name属性为主否则以默认的规则为主
                    String value = annotation.name();
                    if (value!=null && !value.equals("")){
                        beanId = value;
                    }
                    else {
                        beanId = toLowerCaseFirstOne(clazz.getSimpleName());
                    }
                }
                //存储值
                map.put(beanId,object);
            }



        }
        return map;
    }


    /**
     * 初始化依赖的属性
     * @param object
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private void initAttribute(Object object)throws Exception {
        //获取object的所有类型
        Class<? extends Object> classinfo = object.getClass();
        //获取所有的属性字段
        Field[] fields = classinfo.getDeclaredFields();
        //遍历所有字段
        for(Field field : fields){
            //查找字段上有依赖的注解
            boolean falg = field.isAnnotationPresent(MyResource.class);
            if (falg){
                MyResource iocResource = field.getAnnotation(MyResource.class);
                if (iocResource!=null){
                    //获取属性的beanid
                    String beanId = field.getName();
                    //获取对应的object
                    Object attrObject = getBean(beanId);

                    if (attrObject!=null){
                        //访问私有字段
                        field.setAccessible(true);
                        //赋值
                        field.set(object,attrObject);
                        continue;
                    }
                }
            }
        }
    }




    /**
     *
     * 获取包路径下所有class类
     *
     * */
    public static List<Class<?>> getClasses(String packageName) {
        //第一个class类的集合
        List<Class<?>> classes = new ArrayList<Class<?>>();
        ClassUtils.scan(packageName, new ClassUtils.TestHandler() {

            @Override
            public void handle(File file, String className) {
                try {
                    classes.add(Class.forName(className.replaceAll(".class", "")));
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            @Override
            public boolean accept(File file) {
                // TODO Auto-generated method stub
                return file.getName().endsWith(".class");
            }
        });
        return classes;
    }

    /**
     * 首字母转换为小写
     * @param s
     * @return
     */
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))){
            return s;
        }
        else{
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

}
